﻿namespace TanzimSaqib.NoBrainer.Sample.DataAccess
{
    using System.Collections.Generic;
    using System;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Nothing fancy with the repository name. It just means we did not bother to 
    /// create different repositories for this tiny app, rather we put it all in
    /// one single place. Hence, the name SingleRepository.
    /// 
    /// I know we could use Dependency Injection/modularize even more, 
    /// but I wanted to keep the sample simple.
    /// </summary>
    public class SingleRepository : LinqContext, ISingleRepository
    {
        private readonly LinqContext _db;

        public SingleRepository()
        {
            _db = GetDbInstance();
        }

        private aspnet_User GetUser(string userName)
        {
            return _db.aspnet_Users.FirstOrDefault(u => u.LoweredUserName.Equals(userName.ToLowerInvariant()));
        }

        private Blog GetBlog(Guid userId)
        {
            return _db.Blogs.FirstOrDefault(b => b.UserId.Equals(userId));
        }

        public Blog CreateBlog(string userName)
        {
            var user = GetUser(userName);
            return _db.Insert(new Blog {Title = string.Format("{0}'s blog", userName), UserId = user.UserId});
        }

        public Post CreatePost(Post post)
        {
            return _db.Insert(
                new Post
                {
                    Title = post.Title,
                    Body = post.Body,
                    BlogId = GetBlog(post.UserId).ID,
                    Status = post.Status,
                    Created = post.Created,
                    Tags = post.TagList
                });
        }

        public Post GetPost(Post post)
        {
            var existingPost = _db.Posts.FirstOrDefault(p => p.ID == post.ID);

            if (existingPost != default(Post))
            {
                if (post.UserId == default(Guid))
                {
                    var blog = _db.Blogs.FirstOrDefault(b => b.ID == existingPost.BlogId);
                    if (blog != default(Blog))
                    {
                        existingPost.UserId = blog.UserId;
                    }
                }
                else
                {
                    existingPost.UserId = post.UserId;
                }
            }

            return existingPost;
        }

        public IEnumerable<Post> GetPosts(Blog blog)
        {
            var blogId = _db.Blogs.FirstOrDefault(b => b.UserId == blog.UserId).ID;
            return _db.Posts.Where(p => p.BlogId == blogId).OrderByDescending(p => p.Created);
        }

        public Post CreateTags(Post post)
        {
            var tagTokens = post.TagList.Split(',');
            var tagList = string.Empty;
            foreach (var token in tagTokens)
            {
                var localToken = token;
                var tag = _db.Tags.FirstOrDefault(t => t.Title == localToken.ToLowerInvariant().Trim());

                if (tag == default(Tag))
                {
                    var newTag = _db.Insert(new Tag
                    {
                        Title = token.ToLowerInvariant().Trim(),
                    });

                    string.Format("New tag created: {0}-{1}.", newTag.ID, newTag.Title).Trace();
                    tagList += newTag.ID + ",";
                }
                else
                {
                    if (!tagList.StartsWith(tag.ID + ",") && !tagList.Contains(string.Format(",{0},", tag.ID)))
                        tagList += tag.ID + ",";
                }
            }

            post.TagList = tagList;

            return post;
        }

        public Post GetTagList(Post post)
        {
            var existingPost = _db.Posts.FirstOrDefault(p => p.ID == post.ID);
            var tagIds = existingPost.Tags.Split(',');
            var tagList = new StringBuilder();

            foreach (var tag in tagIds.Select(id => _db.Tags.FirstOrDefault(t => t.ID == int.Parse(id))))
            {
                tagList.Append(tag.Title);
                tagList.Append(", ");
            }

            tagList.Remove(tagList.Length - 2, 2);
            post.TagList = tagList.ToString();

            return post;
        }

        public aspnet_User GetUser(Guid userId)
        {
            return _db.aspnet_Users.FirstOrDefault(u => u.UserId == userId);
        }
    }
}
